# coding=utf-8
import arcpy
import os
import sys
import time
import traceback

# 设置默认编码为 UTF-8
try:
    reload(sys)
    sys.setdefaultencoding('utf-8')
except NameError:
    # Python 3 不需要此操作
    pass


# 配置参数
class Config:
    INPUT_GDB = r"D:\ArcGis\DATA\DataExtraction.gdb"  # 输入数据库路径
    TARGET_FC = "ZXLN_JBXX"  # 指定要处理的要素类名称，None表示处理所有要素类
    FIELD_A = "GXMC"  # 名称字段，用于匹配
    FIELD_B = "Shape_Length"  # 长度/面积字段，用于计算相似度
    SIMILARITY_THRESHOLD = 0.9  # 相似度阈值


def create_gdb_if_not_exists(gdb_path):
    """创建文件地理数据库（如果不存在）"""
    try:
        if not arcpy.Exists(gdb_path):
            parent_dir = os.path.dirname(gdb_path)
            if not os.path.exists(parent_dir):
                os.makedirs(parent_dir)
            arcpy.CreateFileGDB_management(parent_dir, os.path.basename(gdb_path))
            print("成功创建地理数据库: %s" % gdb_path)
        return True
    except Exception as e:
        print("创建地理数据库失败: %s, 错误: %s" % (gdb_path, str(e)))
        return False


def ensure_duplicate_field(feature_class):
    """确保要素类包含Duplicate_data字段并初始化为空"""
    try:
        fields = [f.name.upper() for f in arcpy.ListFields(feature_class)]
        if "DUPLICATE_DATA" not in fields:
            print("为要素类 %s 添加Duplicate_data字段" % os.path.basename(feature_class))
            arcpy.AddField_management(feature_class, "Duplicate_data", "LONG")
            with arcpy.da.UpdateCursor(feature_class, ["Duplicate_data"]) as cursor:
                for row in cursor:
                    row[0] = None
                    cursor.updateRow(row)
        return True
    except Exception as e:
        print("处理要素类字段失败: %s, 错误: %s" % (feature_class, str(e)))
        return False


def calculate_relative_error(value_old, value_new, threshold=0.1):
    """计算相对误差并返回相似度结果（0-1）或特殊标记（5）"""
    if value_old == 0 or value_new == 0:
        return 5
    relative_error = abs(value_new - value_old) / max(abs(value_old), abs(value_new))
    return 1 - relative_error


def process_feature_class(fc):
    """处理单个要素类的主函数"""
    try:
        print("\n===== 开始处理要素类: %s =====" % fc)
        start_time = time.time()
        fc_path = os.path.join(Config.INPUT_GDB, fc)

        if not arcpy.Exists(fc_path):
            print("警告: 要素类 %s 不存在" % fc_path)
            return False

        ensure_duplicate_field(fc_path)

        # 预加载旧数据（ADD_DATA为空）的字段A和字段B
        old_data = {}  # key: 字段A值, value: [(object_id, 字段B值)]
        with arcpy.da.SearchCursor(fc_path, ["OBJECTID", "ADD_DATA", Config.FIELD_A, Config.FIELD_B]) as cursor:
            for row in cursor:
                obj_id, add_data, field_a, field_b = row
                if add_data is None and field_a is not None:  # 旧数据且字段A不为空
                    if field_a not in old_data:
                        old_data[field_a] = []
                    old_data[field_a].append((obj_id, field_b))

        # 处理新数据（ADD_DATA=1）
        new_data = []
        with arcpy.da.SearchCursor(fc_path, ["OBJECTID", "ADD_DATA", Config.FIELD_A, Config.FIELD_B]) as cursor:
            for row in cursor:
                obj_id, add_data, field_a, field_b = row
                if add_data == 1 and field_a is not None:  # 新数据且字段A不为空
                    new_data.append((obj_id, field_a, field_b))

        # 遍历新数据
        for new_obj_id, new_field_a, new_field_b in new_data:
            # 查找字段A相同的旧数据
            if new_field_a not in old_data:
                continue  # 无匹配的旧数据，跳过

            # 计算所有字段A相同的旧数据的相似度
            best_similarity = -1
            best_old_obj_id = None
            for old_obj_id, old_field_b in old_data[new_field_a]:
                # 检查旧数据的B字段是否为0，为0则跳过
                if old_field_b == 0:
                    continue

                similarity = calculate_relative_error(old_field_b, new_field_b, Config.SIMILARITY_THRESHOLD)
                if similarity > best_similarity:
                    best_similarity = similarity
                    best_old_obj_id = old_obj_id

            # 处理最佳匹配结果
            if best_similarity >= Config.SIMILARITY_THRESHOLD and best_old_obj_id:
                # 更新双方的Duplicate_data字段
                with arcpy.da.UpdateCursor(fc_path, ["Duplicate_data"], "OBJECTID = %d" % new_obj_id) as new_cursor:
                    for row in new_cursor:
                        row[0] = best_old_obj_id
                        new_cursor.updateRow(row)
                with arcpy.da.UpdateCursor(fc_path, ["Duplicate_data"],
                                           "OBJECTID = %d" % best_old_obj_id) as old_cursor:
                    for row in old_cursor:
                        row[0] = new_obj_id
                        old_cursor.updateRow(row)

        end_time = time.time()
        print("  要素类 %s 处理完成，耗时: %.2f 秒" % (fc, end_time - start_time))
        return True

    except Exception as e:
        print("处理要素类 %s 时出错: %s" % (fc, str(e)))
        traceback.print_exc()
        return False


if __name__ == "__main__":
    try:
        print("===== 开始执行数据匹配分析 =====")
        start_total_time = time.time()
        arcpy.env.workspace = Config.INPUT_GDB
        arcpy.env.overwriteOutput = True

        # 获取所有要素类
        feature_classes = arcpy.ListFeatureClasses()
        if not feature_classes:
            print("数据库中没有找到要素类！")
            sys.exit(1)

        # 确定要处理的要素类
        if Config.TARGET_FC:
            # 处理指定的单个要素类
            if Config.TARGET_FC in feature_classes:
                print("将处理指定的要素类: %s" % Config.TARGET_FC)
                process_feature_class(Config.TARGET_FC)
            else:
                print("错误: 要素类 %s 不存在于数据库中" % Config.TARGET_FC)
                sys.exit(1)
        else:
            # 处理所有要素类
            print("将处理所有 %d 个要素类" % len(feature_classes))
            for fc in feature_classes:
                process_feature_class(fc)

        end_total_time = time.time()
        print("\n===== 全部处理完成，总耗时: %.2f 秒 =====" % (end_total_time - start_total_time))

    except Exception as e:
        print("执行过程中发生错误: %s" % str(e))
        traceback.print_exc()
    finally:
        arcpy.ClearEnvironment("workspace")